package cn.virens.config;

import java.time.Duration;

import javax.cache.CacheManager;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import cn.virens.web.components.weixin.config.WxMpJCacheCacheConfigStorage;
import cn.virens.web.components.weixin.handler.DefulatMessageHandler;
import cn.virens.web.components.weixin.handler.QrsceneMessageHandler;
import cn.virens.web.components.weixin.handler.SubscribeMessageHandler;
import cn.virens.web.components.weixin.handler.UnsubscribeMessageHandler;
import cn.virens.web.components.weixin.session.standard.WxStandardSessionManager;
import cn.virens.web.components.weixin.session.support.SupportSessionManager;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceOkHttpImpl;

@Configuration
public class SpringWeixinMpConfig {
	@Value("${wx.mp.token}")
	private String token;

	@Value("${wx.mp.appid}")
	private String appid;

	@Value("${wx.mp.secret}")
	private String secret;

	@Bean("wxMpConfigStorage")
	public WxMpConfigStorage wxMpConfigStorage(@Qualifier("mManagerFactoryBean") CacheManager factory) {
		WxMpJCacheCacheConfigStorage configStorage = new WxMpJCacheCacheConfigStorage(factory);
		configStorage.setSecret(secret);
		configStorage.setAppId(appid);
		configStorage.setToken(token);

		return configStorage;
	}

	@Bean("wxMpService")
	public WxMpService wxMpService(@Qualifier("wxMpConfigStorage") WxMpConfigStorage config) {
		WxMpServiceOkHttpImpl wxService = new WxMpServiceOkHttpImpl();
		wxService.setWxMpConfigStorage(config);

		return wxService;
	}

	@Bean("wxMpSessionManager")
	public SupportSessionManager wxMpSessionManager() {
		SupportSessionManager supportSessionManager = SupportSessionManager.of(new WxStandardSessionManager());
		supportSessionManager.setMaxInactiveInterval(Duration.ofSeconds(1800));

		return supportSessionManager;
	}

	@Bean("wxMpMessageRouter")
	public WxMpMessageRouter wxMpMessageRouter(@Qualifier("wxMpService") WxMpService wxService) {
		WxMpMessageRouter router = new WxMpMessageRouter(wxService);
		router.setSessionManager(wxMpSessionManager());
		router.rule().async(false).event("subscribe").handler(subscribeMessageHandler()).end();
		router.rule().async(false).event("unsubscribe").handler(unsubscribeMessageHandler()).end();
		router.rule().async(false).eventKeyRegex("^qrscene_.*").handler(qrsceneMessageHandler()).end();
		router.rule().handler(defulatMessageHandler()).end();

		return router;
	}

	@Bean("unsubscribeMessageHandler")
	public UnsubscribeMessageHandler unsubscribeMessageHandler() {
		return new UnsubscribeMessageHandler();
	}

	@Bean("subscribeMessageHandler")
	public SubscribeMessageHandler subscribeMessageHandler() {
		return new SubscribeMessageHandler();
	}

	@Bean("qrsceneMessageHandler")
	public QrsceneMessageHandler qrsceneMessageHandler() {
		return new QrsceneMessageHandler();
	}

	@Bean("defulatMessageHandler")
	public DefulatMessageHandler defulatMessageHandler() {
		return new DefulatMessageHandler();
	}
}
